/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package graf;

import java.util.ArrayList;

/**
 *
 * @author sufka
 */
public class TestyParKrawedzioweAlgorytm implements PokrycieTestowe{

    Graf graf;
    ParKrawedzioweAlgorytm parKAlg;
    ArrayList<Sciezka> testy;
    public TestyParKrawedzioweAlgorytm(Graf graf){
        this.graf = graf;
        parKAlg = new ParKrawedzioweAlgorytm(graf);
        testy = new ArrayList<Sciezka>();
    }

    public void pokaz(ArrayList<Sciezka> as){
        //System.out.println(slowo);
        for(Sciezka s : as){
            System.out.println("kolejna "+as.indexOf(s));
            for(Wierzcholek w : s.getNaSciezce()){
                System.out.print(w.getNumer()+" ");
            }
            System.out.println("");
        }
        System.out.println("\n");
    }

    public void tworzPokrycie() {
        ArrayList<Sciezka> tmpPaths = parKAlg.tworzPokrycie();
        int q = 0;
        while(q < tmpPaths.size()){
            if(tmpPaths.get(q).pierwszy().getNumer() == -1){
                while(tmpPaths.get(tmpPaths.size()-1).pierwszy().getNumer() != -1 ){
                    tmpPaths.remove(tmpPaths.size()-1);
                }
                if(tmpPaths.get(tmpPaths.size()-1).pierwszy().getNumer() == -1){
                    tmpPaths.remove(tmpPaths.size()-1);
                }
                break;
            }else{
                q++;
            }
        }
        //bo wlasnie ten warunek byl z numerem -1

        do{

            Sciezka currentPath;
            int maxLen = tmpPaths.get(0).dlugoscSciezki();
            int maxi = 0;
            for(int i = 1; i < tmpPaths.size(); ++i){
		Sciezka pathi = tmpPaths.get(i);
		if(pathi.dlugoscSciezki() > maxLen){
                    maxLen = pathi.dlugoscSciezki();
                    maxi = i;
		}
            }

            currentPath = tmpPaths.get(maxi);

            tmpPaths.remove(maxi);

            if(currentPath.isTestPath(graf)){
		filterSubpaths(tmpPaths, currentPath);
                testy.add(currentPath);
		continue;
            }

            do{

                filterSubpaths(tmpPaths, currentPath);

                if(tmpPaths.size() > 0){
                    //search for longest overlap and merge
                    int maxoverlap = tmpPaths.get(0).intersects(currentPath);
                    int maxi2 = 0;

                    for(int i = 1; i < tmpPaths.size(); ++i){
                        Sciezka pathi = tmpPaths.get(i);
			int overlap = pathi.intersects(currentPath);
			// lets choose an open path over those which end
			if(maxoverlap > 0 && overlap == maxoverlap){
                            if(tmpPaths.get(maxi2).isBorderPath(graf)){
                                maxi2 = i;
                            }
                            if(overlap > maxoverlap){
                                maxoverlap = overlap;
				maxi2 = i;
                            }
                        }
                    }

                    if(maxoverlap != 0){
                        Sciezka maxPath = tmpPaths.get(maxi2);
                        Sciezka merged = currentPath.mergedWith(maxPath);

			tmpPaths.remove(maxPath);
			currentPath = merged;
			continue;
                    }
                }

                if(tmpPaths.size() > 0){
                    boolean append = true;
                    int maxi3 = -1;
                    int maxlen = -1;
                    //find longest path that can be appended
                    for(int i = 0; i < tmpPaths.size(); ++i){
                        Sciezka pathi = tmpPaths.get(i);
    			if(pathi.dlugoscSciezki() > maxlen){
                            if(currentPath.ostatni().czyZawieraSasiada(pathi.pierwszy())){
                                maxlen = pathi.dlugoscSciezki();
				maxi3 = i;
                            }
                        }
                    }

                    //find longest path that can be prepended
                    for(int i = 0; i < tmpPaths.size(); ++i){
                        Sciezka pathi = tmpPaths.get(i);
			if(pathi.dlugoscSciezki() > maxlen){
                            if(pathi.ostatni().czyZawieraSasiada(currentPath.pierwszy())){
                                maxlen = pathi.dlugoscSciezki();
                                maxi3 = i;
				append = false;
                            }
                        }
                    }

                    if(maxi3 != -1){
                        Sciezka pathi = tmpPaths.get(maxi3);
                        if(append){
                            currentPath.appendPath(pathi);
                        }else{
                            currentPath.prependPath(pathi);
			}
			tmpPaths.remove(pathi);
			continue;
                    }
                }

                boolean append = true;
		int mindist = 0xFFFFFFF;
		int mini4 = -1;

                // finally search for nodes that are closest to end...
                for(int i = 0; i < this.graf.getWierzcholki().size(); ++i){
                    Wierzcholek  w = this.graf.getWierzcholki().get(i);
                    int dist = w.distanceToNearestEndNode(null, graf);
                    if(dist < mindist){
                        if(currentPath.ostatni().czyZawieraSasiada(w) && currentPath.ostatni() != w){
                            mindist = dist;
                            mini4 = i;
			}
                    }
                }

                // ...or start
                for(int i = 0; i < this.graf.getWierzcholki().size(); ++i){
                    Wierzcholek w = this.graf.getWierzcholki().get(i);
                    int dist = w.distanceToNearestStartNode(null, graf);
                    if(dist < mindist){
                        if(w.czyZawieraSasiada(currentPath.pierwszy()) && w != currentPath.pierwszy()){
                            mindist = dist;
                            mini4 = i;
                            append = false;
                        }
                    }
		}

                if(mini4 != -1){
                    if(append){
                        currentPath.dodajNaKoniec(this.graf.getWierzcholki().get(mini4));
                    }else{
                        currentPath.dodajNaPoczatek(this.graf.getWierzcholki().get(mini4));
                    }
                }

            }while(!currentPath.isTestPath(graf));

            filterSubpaths(tmpPaths, currentPath);
            testy.add(currentPath);
        }while(tmpPaths.size() > 0);
    }

    public void filterSubpaths(ArrayList<Sciezka>  wymagania, Sciezka path){
        int i = 0;
        while(i < wymagania.size()){
            Sciezka ss = wymagania.get(i);
            if(path.containsPath(ss)){
                wymagania.remove(ss);
            }else{
                i++;
            }
	}
    }

    public void pokaz(Sciezka s, String slowo){
        System.out.println(slowo);
        for(Wierzcholek w : s.getNaSciezce()){
            System.out.print(w.getNumer()+" ");
        }
        System.out.println("\n");
    }

    public ArrayList<Sciezka> getTesty() {
        return testy;
    }

    public void setTesty(ArrayList<Sciezka> testy) {
        this.testy = testy;
    }
}
